package com.it.web.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.it.common.domain.dos.ArticleCategoryRelDO;
import com.it.common.domain.dos.ArticleDO;
import com.it.common.domain.dos.CategoryDO;
import com.it.common.enums.ResponseCodeEnum;
import com.it.common.exception.BizException;
import com.it.common.mapper.ArticleCategoryRelMapper;
import com.it.common.mapper.ArticleMapper;
import com.it.common.mapper.CategoryMapper;
import com.it.common.utils.PageResponse;
import com.it.common.utils.Response;
import com.it.web.convert.ArticleConvert;
import com.it.web.model.dto.category.FindCategoryArticlePageListDto;
import com.it.web.model.dto.category.FindCategoryLisDto;
import com.it.web.model.vo.category.FindCategoryArticlePageListRspVO;
import com.it.web.model.vo.category.FindCategoryListRspVO;
import com.it.web.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, CategoryDO> implements CategoryService {

    @Resource
    private CategoryMapper categoryMapper;

    @Resource
    private ArticleMapper articleMapper;

    @Resource
    private ArticleCategoryRelMapper articleCategoryRelMapper;

    @Override
    public Response findCategoryList(FindCategoryLisDto findCategoryLisDto) {
        Long size = findCategoryLisDto.getSize();

        List<CategoryDO> categoryDOS = null;
        // 如果接口入参中未指定 size
        if (Objects.isNull(size) || size == 0) {
            // 查询所有分类
            categoryDOS = categoryMapper.findCategorySelectList();
        } else {
            // 否则查询指定的数量
            categoryDOS = categoryMapper.selectByLimit(size);
        }


        List<FindCategoryListRspVO> vos = new ArrayList<>();
        if(categoryDOS!=null&&categoryDOS.size()>0){
            vos = categoryDOS.stream()
                    .map(categoryDO -> FindCategoryListRspVO.builder()
                            .id(categoryDO.getId())
                            .name(categoryDO.getName()).articlesTotal(categoryDO.getArticlesTotal()).build())
                    .collect(Collectors.toList());

        }
        return Response.success(vos);
    }

    @Override
    public Response findCategoryArticlePageList(FindCategoryArticlePageListDto findCategoryArticlePageListDto) {
        Long current = findCategoryArticlePageListDto.getCurrent();
        Long size = findCategoryArticlePageListDto.getSize();
        Long categoryId = findCategoryArticlePageListDto.getId();

        CategoryDO categoryDO = categoryMapper.selectById(categoryId);
        // 判断该分类是否存在
        if (Objects.isNull(categoryDO)) {
            log.warn("==> 该分类不存在, categoryId: {}", categoryId);
            throw new BizException(ResponseCodeEnum.CATEGORY_NOT_EXISTED);
        }
        // 先查询该分类下所有关联的文章 ID
        List<ArticleCategoryRelDO> articleCategoryRelDOS = articleCategoryRelMapper.selectListByCategoryId(categoryId);
        // 若该分类下未发布任何文章
        if(Objects.isNull(articleCategoryRelDOS)){
            log.info("==> 该分类下还未发布任何文章, categoryId: {}", categoryId);
            return PageResponse.success(null, null);
        }
        List<Long> articleIds = articleCategoryRelDOS.stream()
                .map(articleCategoryRelDO -> articleCategoryRelDO.getArticleId()).collect(Collectors.toList());

        // 根据文章 ID 集合查询文章分页数据
        Page<ArticleDO> page = articleMapper.selectPageListByArticleIds(current, size, articleIds);
        List<ArticleDO> articleDOS = page.getRecords();
        // DO 转 VO
        List<FindCategoryArticlePageListRspVO> vos = new ArrayList<>();
        if(!CollectionUtils.isEmpty(articleDOS)){
            vos = articleDOS.stream().map(articleDO -> ArticleConvert.INSTANCE.convertDO2CategoryArticleVO(articleDO)).collect(Collectors.toList());
        }
        return PageResponse.success(page, vos);
    }
}
